package main

import (
	"log"
	"net"
	"ospf/common"
	"ospf/msgs"
	"ospf/tables"
	"ospf/tools"
)

/*
processHello 处理hello包，如果邻居处于two way状态，就发送lsu包
p 数据包
inf 接收到的网卡
ots 数据库操作对象
*/
func processHello(p msgs.Packet, inf *net.Interface, ots *tables.OspfLSDB) {
	h, ok := p.(*msgs.Hello)
	if !ok {
		log.Fatalf("processHello: not a Hello packet %+v", p)
	}
	stat := common.Init
	for _, nei := range h.NeighborIDs {
		if nei == ots.RouterID {
			stat = common.TowWay
			break
		}
	}
	ots.NeighT.Update(h.DesignatedRouterID, inf, h.BackupDesignatedRouterID, uint8(stat))
}

func processLSU(p msgs.Packet, conn *tools.Conn, nPackage chan bool, t *tables.OspfLSDB) {
	lsu, ok := p.(*msgs.LinkStateUpdate)
	if !ok {
		log.Fatalf("processLSU: not a LinkStateUpdate packet %+v", p)
	}
	received := true
	// 处理并提取相关链路数据
	for _, lsa := range lsu.LSA {
		nodes, src, edges, weights := lsa.(*msgs.RouterLSA).ExtractInfo()
		// 对nodes和edges进行判重，数据库检验。
		if t.LinkStateT.AddNodes(nodes) {
			received = false
		}
		if t.LinkStateT.AddEdgesSingleSrc(src, edges, weights) {
			received = false
		}
	}
	if !received {
		// 接收到没有处理过的包，需要转发
		if len(nPackage) == 0 {
			nPackage <- true
		}
		err := conn.Write(lsu, tools.AllSPFRouters)
		if err != nil {
			log.Fatalf("processLSU: packet forward failed: %v", err)
		}

	}
}
